home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / B-C / C++Source Code Fmtr Folder / Tests / UPrinting.cp < prev    next >
Encoding:
Text File  |  1991-01-28  |  60.6 KB  |  2,219 lines  |  [TEXT/MPS ]

  1. // UPrinting.cp
  2. // Copyright © 1986-1990 by Apple Computer, Inc.  All rights reserved.
  3.  
  4. /*
  5.   Segmentation strategy:
  6.   PrintRes  Resident
  7.   PrintMain Resident and used at initialization
  8.   PrintActual Used only during Actual Printing (imaging/spooling)
  9.   PrintImage    Used during imaging only
  10.   PrintSpool    Used only during printing of a Spool File
  11.   PrintDebug    Debugging code
  12.   PrintFinder Code only ever accessed from Finder Printing
  13.   PrintInit One-time Initialization Code
  14.   PrintOpen Code accessed when opening new document
  15.   PrintNonRes General non-resident code
  16.   PrintDoCommand   Code for Page Setup command
  17.   PrintTerminate   One-time-only code, called only at Termination time
  18. */
  19.  
  20. #ifndef __ULIST__
  21. #include <UList.h>
  22. #endif
  23.  
  24. #ifndef __EDITIONS__
  25. #include <Editions.h>
  26. #endif
  27.  
  28. #ifndef __UAPPLICATION__
  29. #include <UApplication.h>
  30. #endif
  31.  
  32. #ifndef __UDOCUMENT__
  33. #include <UDocument.h>
  34. #endif
  35.  
  36. #ifndef __BALLOONS__
  37. #include <Balloons.h>
  38. #endif
  39.  
  40. #ifndef __UVIEW__
  41. #include <UView.h>
  42. #endif
  43.  
  44. #ifndef __UWINDOW__
  45. #include <UWindow.h>
  46. #endif
  47.  
  48. #ifndef __UFAILURE__
  49. #include <UFailure.h>
  50. #endif
  51.  
  52. #ifndef __UMACAPPUTILITIES__
  53. #include <UMacAppUtilities.h>
  54. #endif
  55.  
  56. #ifndef __UERRORMGR__
  57. #include <UErrorMgr.h>
  58. #endif
  59.  
  60. #ifndef __UPATCH__
  61. #include <UPatch.h>
  62. #endif
  63.  
  64. #ifndef __UMEMORY__
  65. #include <UMemory.h>
  66. #endif
  67.  
  68. #ifndef __UMACAPPGLOBALS__
  69. #include <UMacAppGlobals.h>
  70. #endif
  71.  
  72. #ifndef __UVIEWCOORDS__
  73. #include <UViewCoords.h>
  74. #endif
  75.  
  76. #ifndef __MENUS__
  77. #include <Menus.h>
  78. #endif
  79.  
  80. #ifndef __UMENUMGR__
  81. #include <UMenuMgr.h>
  82. #endif
  83.  
  84. #ifndef __TOOLUTILS__
  85. #include <ToolUtils.h>
  86. #endif
  87.  
  88. #ifndef __PACKAGES__
  89. #include <Packages.h>
  90. #endif
  91.  
  92. #ifndef __FONTS__
  93. #include <Fonts.h>
  94. #endif
  95.  
  96. #ifndef __ERRORS__
  97. #include <Errors.h>
  98. #endif
  99.  
  100. #ifndef __RESOURCES__
  101. #include <Resources.h>
  102. #endif
  103.  
  104. #ifndef __STDLIB__
  105. #include <StdLib.h>                // for abs()
  106. #endif
  107.  
  108. #ifndef __UPRINTING__
  109. #include <UPrinting.h>
  110. #endif
  111.  
  112. //--------------------------------------------------------------------------------------------------
  113. PenState gBreaksPenState;
  114. Boolean gCancelAllPrinting;
  115. VRect gStdPageMargins;
  116. Handle gFinderHPrint;
  117. TStdPrintHandler* gJobPrintHandler;
  118.  
  119. //--------------------------------------------------------------------------------------------------
  120. typedef Str255* String255Ptr;
  121. typedef String255Ptr* String255Handle;
  122.  
  123. // subclass may stuff some special values by redefining this 
  124. union TXWord
  125. {
  126.     struct
  127.     {
  128.         char c1, c0;
  129.     } charVal;
  130.     struct
  131.     {
  132.         SignedByte b1, b0;
  133.     } byteVal;
  134.     struct
  135.     {
  136.         Boolean f15, f14, f13, f12, f11, f10, f9, f8, f7, f6, f5, f4, f3, f2, f1, f0;
  137.     } boolVal;
  138.     short iO;
  139. };
  140.  
  141. //--------------------------------------------------------------------------------------------------
  142. #pragma segment PrintRes
  143.  
  144. pascal void TPrintCommand::DoIt(void)
  145. {
  146.     Boolean proceed;
  147.  
  148.     fStdPrintHandler->Print(fCmdNumber, proceed);
  149. }
  150.  
  151. //--------------------------------------------------------------------------------------------------
  152. #pragma segment PrintSelCommand
  153.  
  154. pascal void TPrintCommand::Initialize(void)        // override 
  155. {
  156.     inherited::Initialize();
  157.     fStdPrintHandler = NULL;
  158. }
  159.  
  160. //--------------------------------------------------------------------------------------------------
  161. #pragma segment PrintSelCommand
  162.  
  163. pascal void TPrintCommand::IPrintCommand(CmdNumber itsCmdNumber,
  164.                                          TStdPrintHandler* itsStdPrintHandler)
  165. {
  166.     this->INoChangesCommand(itsCmdNumber, itsStdPrintHandler->fDocument, itsStdPrintHandler->fView);
  167.     fStdPrintHandler = itsStdPrintHandler;
  168. }
  169.  
  170. //--------------------------------------------------------------------------------------------------
  171. #pragma segment MAFields
  172.  
  173. pascal void TPrintCommand::Fields(TObject* obj)    // override 
  174. {
  175.     obj->DoToField("TPrintCommand", NULL, bClass);
  176.     obj->DoToField("fStdPrintHandler", &fStdPrintHandler, bObject);
  177.     inherited::Fields(obj);
  178. }
  179.  
  180. //--------------------------------------------------------------------------------------------------
  181. #pragma segment PrintActual
  182. //$Push
  183. // #if qTrace
  184. //$D+
  185. //#endif  No tracing till we get the port straightened out since the current
  186. //port could already be disposed (Thank you Direct connect ImageWriter!)
  187.  
  188. pascal void IdleProcForTStdPrintHandler(void)
  189. {
  190.     GrafPtr savedPort;
  191.  
  192.     if (gJobPrintHandler)
  193.     {
  194.         GetPort(savedPort);
  195.         SetPort(gWorkPort);                        // Nice safe port in a storm 
  196.         gJobPrintHandler->DoPrintIdling();        // Forward to the current print job handler 
  197.         SetPort(savedPort);
  198.     }
  199. }
  200. //$Pop
  201.  
  202. //--------------------------------------------------------------------------------------------------
  203. #pragma segment PrintActual
  204.  
  205. pascal void TStdPrintHandler::DoPrintIdling(void)
  206. {
  207.     const short myDlgMask = mDownMask + mUpMask + keyDownMask + keyUpMask + autoKeyMask;
  208.  
  209.     char ch;
  210.     short keycode;
  211.     DialogPtr aDialog;
  212.     TDeviceEvent * event;
  213.     EventRecord anEventRecord;
  214.     short item;
  215.     Handle theItem;
  216.     short itemType;
  217.     Rect box;
  218.     long dontCare;
  219.  
  220.     event = gApplication->GetEvent(myDlgMask, 0, NULL);
  221.     if (event)
  222.     {
  223.         // Workaround for LaserWriter driver bug: it tries to set GhostWindow
  224.         // so that its status window is invisible. Unfortunately, it doesn't
  225.         // always set it, so IsDialogEvent returns FALSE (the status window
  226.         // is frontmost).  If ours isn't already in front, force it there.
  227.         if (fPrintDialog != FrontWindow())
  228.             gApplication->SelectWMgrWindow(fPrintDialog);
  229.  
  230.         switch (event->fEventRecord.what)
  231.         {
  232.             case keyDown:
  233.                 ch = (char)(event->fEventRecord.message & charCodeMask);
  234.                 keycode = (short)((event->fEventRecord.message >> keyCodeMask) & 8);
  235.                 if (((ch == '.') && event->fCmdKey) || ((ch == chEscape) && (keycode == kEscapeVirtualCode)))
  236.                 {
  237.  
  238.                     /*### need a way to determine if multiple file printing is in process
  239.                       if (gFinderPrinting)
  240.                       item = cancel;                // Want the 'Cancel All' button 
  241.                       else
  242.                       item = 1;                    // Want the 'Cancel' button 
  243.                     */
  244.                     item = 1;
  245.  
  246.                     // Flash the appropriate button 
  247.                     GetDItem(fPrintDialog, item, itemType, theItem, box);
  248.                     HiliteControl((ControlHandle)theItem, 10);
  249.                     Delay(8, dontCare);
  250.                     HiliteControl((ControlHandle)theItem, 0);
  251.  
  252.                     PrSetError(iPrAbort);
  253.                     gCancelAllPrinting = TRUE;
  254.                 }
  255.                 break;
  256.  
  257.             default:
  258.                 anEventRecord = event->fEventRecord;
  259.                 if (IsDialogEvent(anEventRecord) && DialogSelect(anEventRecord, aDialog, item) && (aDialog == fPrintDialog))
  260.                     switch (item)
  261.                     {
  262.                         case 1:
  263.                             PrSetError(iPrAbort);// Cancel
  264.                             break;
  265.  
  266.                         case cancel:            // Cancel All Printing 
  267.                             PrSetError(iPrAbort);
  268.                             gCancelAllPrinting = TRUE;
  269.                             break;
  270.                     }
  271.                 break;
  272.         }
  273.     }
  274. }
  275.  
  276. //--------------------------------------------------------------------------------------------------
  277. #pragma segment PrintActual
  278.  
  279. pascal void TStdPrintHandler::ChkPrintErr(OSErr& err,
  280.                                           Boolean& proceed,
  281.                                           Boolean& ranOutOfSpace)
  282. {
  283.     if (proceed)
  284.     {
  285.         err = PrError();
  286.         if (err != noErr)
  287.         {
  288. #if qDebug
  289.             if (gDebugPrinting)
  290.                 cout << "Error from PrError is " << err << "\n";
  291. #endif
  292.  
  293.             proceed = FALSE;
  294.             if (err == -1)
  295.                 ranOutOfSpace = TRUE;
  296.         }
  297.     }
  298. }
  299.  
  300. //--------------------------------------------------------------------------------------------------
  301. #pragma segment PrintRes
  302.  
  303. pascal void TStdPrintHandler::GetDriverName(Str255& driverName)
  304. {
  305.     String255Handle driverHandle;
  306.  
  307.     driverHandle = (String255Handle)GetString((short)kPrintDriverName);// Get current driver 
  308.  
  309.     // Be a little cautious, in case we accidentally pick up something
  310.     // which is not what we expect, or we can't find it.
  311.     if (driverHandle && ((**driverHandle).Length() < 64))
  312.         CopyStr255(**driverHandle, (Ptr) & driverName);
  313.     else
  314.         driverName = "";
  315. }
  316.  
  317. //--------------------------------------------------------------------------------------------------
  318. #pragma segment PrintInit
  319. // Initialize the printing unit.  Call exactly once 
  320.  
  321. pascal void InitUPrinting(void)
  322. {
  323.     TStdPrintHandler * aStdPrintHandler;
  324.  
  325.     gCancelAllPrinting = FALSE;
  326.     gFinderHPrint = NULL;
  327.     gJobPrintHandler = NULL;
  328.  
  329.     SetVRect(gStdPageMargins, 72, 72, -72, -72);// 1" margins std default 
  330.  
  331.     gBreaksPenState.pnLoc = gZeroPt;
  332.     gBreaksPenState.pnSize = Point(2, 2);
  333.     gBreaksPenState.pnMode = patCopy;
  334.     StuffHex((Ptr) & gBreaksPenState.pnPat, "CC663399CC663399");
  335.  
  336.     gCouldPrint = TRUE;
  337.  
  338.     gUPrintingInitialized = TRUE;
  339.  
  340.     if (gPrintHandler == gNullPrintHandler)
  341.     {
  342.         // Install a StdPrintHandler in UMacApp
  343.         // global variable gPrintHandler
  344.         aStdPrintHandler = new TStdPrintHandler;
  345.         aStdPrintHandler->IStdPrintHandler(NULL, NULL, kSquareDots, kFixedSize, kFixedSize);
  346.         aStdPrintHandler->fFinderJobDialog = TRUE;
  347.         gPrintHandler = aStdPrintHandler;
  348.     }
  349. }
  350.  
  351. //--------------------------------------------------------------------------------------------------
  352. #pragma segment MAPrintingRes
  353. // Synonym For InitUPrinting 
  354.  
  355. pascal void InitPrinting(void)
  356. {
  357.     InitUPrinting();
  358. }
  359.  
  360. //--------------------------------------------------------------------------------------------------
  361. #pragma segment PrintSpool
  362.  
  363. pascal void TStdPrintHandler::PrintSpoolFile(Handle anHPrint,
  364.                                              OSErr& err,
  365.                                              Boolean& proceed)
  366. {
  367.     TPrStatus prStatus;
  368.     Boolean b;
  369.  
  370.     proceed = TRUE;
  371.     PrPicFile((THPrint)anHPrint, NULL, NULL, NULL, prStatus);
  372.     this->ChkPrintErr(err, proceed, b);
  373. }
  374.  
  375. //--------------------------------------------------------------------------------------------------
  376. #pragma segment PrintOpen
  377.  
  378. pascal void TStdPrintHandler::Initialize(void)    // override 
  379. {
  380. #if qDebug
  381.     if (!gUPrintingInitialized)
  382.     {
  383.         ProgramBreak("InitUPrinting must be called before creating a print handler.");
  384.         Failure(noErr, 0);
  385.     }
  386. #endif
  387.  
  388.     inherited::Initialize();
  389.     fFinderJobDialog = FALSE;
  390.     fFinderSetup = FALSE;
  391.     fFixedSizePages[hSel] = kFixedSize;
  392.     fFixedSizePages[vSel] = kFixedSize;
  393.     fHPrint = NULL;
  394.     fLastBreak = gZeroVPt;
  395.     fLastPrinterName = NULL;
  396.     fLastStrip = VPoint(MAXINT, MAXINT);
  397.     fMarginRes.h = 72;
  398.     fMarginRes.v = 72;
  399.     fMinimalMargins = FALSE;
  400.     fPageAreas.theMargins = gStdPageMargins;    //!!! What about other fields? 
  401.     fPageDirection = vSel;                        // Page 2 is below page 1, etc. 
  402.     fPageStrips = gZeroVPt;                        //!!! Another default? 
  403.     fPPrPort = NULL;
  404.     fPrintDialog = NULL;
  405.     fPrinterDev = kNeverInitialized;
  406.     fPrintExtent = gZeroVRect;                    //!!! Another default? 
  407.     fShowBreaks = FALSE;
  408.     fSquareDots = kSquareDots;
  409.     fStartPage = 1;
  410.     fViewedRect = gZeroVRect;                    //!!! Another default? 
  411.  
  412. }
  413.  
  414. //--------------------------------------------------------------------------------------------------
  415. #pragma segment PrintOpen
  416.  
  417. pascal void TStdPrintHandler::IStdPrintHandler(TDocument* itsDocument,
  418.                                                TView* itsView,
  419.                                                Boolean itsSquareDots,
  420.                                                Boolean itsHFixedSize,
  421.                                                Boolean itsVFixedSize)
  422. {
  423.     FailInfo fi;
  424.  
  425.     this->IPrintHandler(itsView);
  426.     fDocument = itsDocument;
  427.     fSquareDots = itsSquareDots;
  428.     fFixedSizePages[hSel] = itsHFixedSize;
  429.     fFixedSizePages[vSel] = itsVFixedSize;
  430.  
  431.     if (!fi.CatchFailure())
  432.     {
  433.         if (itsView)
  434.         {
  435.             // allocates a handle for the print-info, and sets my field fHPrint accordingly 
  436.             this->SetDefaultPrintInfo();
  437.  
  438.             if (itsDocument != NULL)
  439.                 itsDocument->AttachPrintHandler(this);
  440.  
  441.             fView->AttachPrintHandler(this);
  442.         }
  443.         fi.Success();
  444.     }
  445.     else
  446.     {
  447.         this->Free();
  448.         fi.ReSignal();
  449.     }
  450. }
  451.  
  452. //--------------------------------------------------------------------------------------------------
  453. #pragma segment PrintClose
  454.  
  455. pascal void TStdPrintHandler::Free(void)        // override 
  456. {
  457.     Boolean dontDispose;
  458.     TDocument * itsDocument;
  459.  
  460.     dontDispose = (fView != NULL);
  461.     if (dontDispose)
  462.     {
  463.         if (fView->fPrintHandler == this)
  464.             fView->AttachPrintHandler(gNullPrintHandler);
  465.         fView = NULL;
  466.  
  467.         itsDocument = fDocument;
  468.         dontDispose = (itsDocument != NULL);
  469.         if (dontDispose)
  470.         {
  471.             if (itsDocument->fDocPrintHandler == this)
  472.                 itsDocument->fDocPrintHandler = NULL;
  473.             dontDispose = itsDocument->fSharePrintInfo;
  474.         }
  475.         if (dontDispose)
  476.             dontDispose = (itsDocument->fPrintInfo == fHPrint);
  477.         fDocument = NULL;
  478.  
  479.     }
  480.     if (!dontDispose)
  481.         fHPrint = DisposeIfHandle(fHPrint);
  482.     fHPrint = NULL;                                // Always drop my reference 
  483.  
  484.     fLastPrinterName = (StringHandle)DisposeIfHandle((Handle)fLastPrinterName);
  485.  
  486.     this->BanishPrintDialog();
  487.  
  488.     if (gJobPrintHandler == this)                // let's be safe 
  489.         gJobPrintHandler = NULL;
  490.  
  491.     inherited::Free();
  492. }
  493.  
  494. //--------------------------------------------------------------------------------------------------
  495. #pragma segment PrintImage
  496.  
  497. pascal void TStdPrintHandler::AdornPage(void)
  498. {
  499. #if qDebug
  500.     const short botSlop = 8;                    // ??? Arbitrary choice 
  501.  
  502.     Str255 heading;
  503.     Str255 pgStr;
  504.     VRect handyRect;
  505.     Rect handyQDRect;
  506.     long itsWidth;
  507.     long rPlusL;
  508.     long itsBottom;
  509.     FontInfo theFontInfo;
  510.     Rect theTextRect;
  511.  
  512.     if (gDebugPrinting)                            // Print extra stuff if debugging 
  513.     {
  514.         NumToString(fFocusedPage, pgStr);
  515.         TextFont(applFont);
  516.         TextFace(normal);
  517.         TextSize(12);
  518.         heading = "-" + pgStr + "-";            // ??? Make easier for client to change this
  519.  
  520.         // draw the heading
  521.         itsWidth = StringWidth(heading);
  522.         rPlusL = fPageAreas.thePaper.right + fPageAreas.thePaper.left;
  523.         itsBottom = fPageAreas.theInk.bottom - botSlop;
  524.         GetFontInfo(theFontInfo);
  525.         theTextRect.left = (short)(rPlusL - itsWidth) / 2;
  526.         theTextRect.top = (short)itsBottom - theFontInfo.ascent;
  527.         theTextRect.right = (short)(theTextRect.left + itsWidth);
  528.         theTextRect.bottom = (short)itsBottom + theFontInfo.descent;
  529.         MADrawString(heading, theTextRect, teFlushDefault);
  530.  
  531.         // Additionally frame the printable area of the page if gDebugPrinting 
  532.         handyRect = fPageAreas.theInk;
  533.         fView->ViewToQDRect(handyRect, handyQDRect);
  534.  
  535.         PenSize(1, 1);
  536.         FrameRect(handyQDRect);
  537.  
  538.         // Frame the 'interior' of the page 
  539.         handyRect = fPageAreas.theInterior;
  540.         fView->ViewToQDRect(handyRect, handyQDRect);
  541.  
  542.         PenSize(2, 2);
  543.         FrameRect(handyQDRect);
  544.     }
  545. #endif
  546.  
  547. }
  548.  
  549. //--------------------------------------------------------------------------------------------------
  550. #pragma segment PrintActual
  551.  
  552. pascal void TStdPrintHandler::BanishPrintDialog(void)
  553. {
  554.     if (fPrintDialog)
  555.     {
  556.         if (fPrintDialog == qd.thePort)            // Only need to invalidate focus if freed
  557.         // dialog is the current port
  558.         {
  559.             gApplication->InvalidateFocus();
  560.             SetPort(gWorkPort);
  561.         }
  562.         DisposDialog(fPrintDialog);
  563.         fPrintDialog = NULL;
  564.     }
  565. }
  566.  
  567. //--------------------------------------------------------------------------------------------------
  568. #pragma segment PrintRes
  569.  
  570. // Called from fView->DoBreakFollowing(), 
  571. pascal VCoordinate TStdPrintHandler::BreakFollowing(VHSelect vhs,
  572.                                                     VCoordinate prevBreak,
  573.                                                     Boolean& automatic)// override 
  574. {
  575.     VHSelect orthoVHS;
  576.     VCoordinate newLoc;
  577.  
  578.     orthoVHS = gOrthogonal[vhs];
  579.     automatic = TRUE;
  580.     newLoc = Min(prevBreak + fViewPerPage[orthoVHS], fPrintExtent[botRight][orthoVHS]);
  581.  
  582. #if qDebug
  583.     if (newLoc <= prevBreak)
  584.     {
  585.         cout << form("No advance in BreakFollowing; vhs: %1d prevBreak: %1d newLoc: %1d view size: ", (short)vhs, prevBreak, newLoc, fPrintExtent[botRight][orthoVHS]);
  586.         ProgramBreak("No advance in BreakFollowing");
  587.     }
  588. #endif
  589.  
  590.     return newLoc;
  591. }
  592.  
  593. //--------------------------------------------------------------------------------------------------
  594. #pragma segment PrintNonRes
  595.  
  596. pascal Boolean FindLimit(VCoordinate,
  597.                          Boolean,
  598.                          void* staticLink)
  599. {
  600.     ++(*((long*)staticLink));
  601.     return FALSE;
  602. }
  603.  
  604.  
  605. pascal void TStdPrintHandler::CalcPageStrips(VPoint& pageStrips)// override 
  606. {
  607.     VHSelect ortho;
  608.     long nStrips;
  609.  
  610.     // If pages are of fixed size, then simple divide the total size by the
  611.     // page size.  Otherwise, count up the page breaks one by one.
  612.  
  613.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  614.     {
  615.         ortho = gOrthogonal[vhs];
  616.         if (fFixedSizePages[ortho])
  617.             pageStrips[vhs] = (fPrintExtent[botRight][ortho] - fPrintExtent[topLeft][ortho] + fViewPerPage[ortho] - 1) / fViewPerPage[ortho];
  618.         else
  619.         {
  620.             nStrips = 0;
  621.             this->EachBreak(vhs, TRUE, FindLimit, &nStrips);
  622.             pageStrips[vhs] = nStrips;
  623.         }
  624.     }
  625. }
  626.  
  627. //--------------------------------------------------------------------------------------------------
  628. #pragma segment PrintNonRes
  629.  
  630. pascal void TStdPrintHandler::CalcViewPerPage(VPoint& amtPerPage)// override 
  631. {
  632.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  633.         amtPerPage[vhs] = Max(1, (fPageAreas.thePaper[botRight][vhs] - fPageAreas.thePaper[topLeft][vhs] - labs(fPageAreas.theMargins[topLeft][vhs]) - labs(fPageAreas.theMargins[botRight][vhs])));
  634. }
  635.  
  636. //--------------------------------------------------------------------------------------------------
  637. #pragma segment PrintRes
  638.  
  639. // this msg is sent to all views if my associated document is the kind where one
  640. // copy of the PrintInfo is shared among all views
  641. pascal void ItChanged(TView* aView,
  642.                       void*)
  643. {
  644.     aView->DoPrinterChanged();
  645. }
  646.  
  647.  
  648. pascal void TStdPrintHandler::CheckPrinter(void)// override 
  649. {
  650.     PageAreas oldPageAreas = fPageAreas;
  651.     long oldPrinterDev = fPrinterDev;
  652.     Point oldDevRes(fDeviceRes);
  653.     Point oldMarginRes(fMarginRes);
  654.     Boolean didChange;
  655.     Boolean msgSent;
  656.     Str255 driverName;
  657.     VRect aRect,  bRect;
  658.  
  659.     // It costs an open and several LoadResources to call PrValidate.  Before
  660.     // doing so, check to see if the printer has actually changed.
  661.     this->GetDriverName(driverName);
  662.     if (!fLastPrinterName || (!EqualString(**fLastPrinterName, driverName, FALSE, TRUE)))
  663.     {
  664.         // Printer name has changed… 
  665.         fLastPrinterName = (StringHandle)DisposeIfHandle((Handle)fLastPrinterName);// out with the old 
  666.         fLastPrinterName = NewString(driverName);// in with the new 
  667.         FailNIL(fLastPrinterName);
  668.         this->ValidatePrintRecord(didChange);            // …and validate the print record. 
  669.     }
  670.  
  671.     // Store latest data from MacPrint prInfo record into my own instance variables
  672.     RectToVRect(((TPPrint) * fHPrint)->rPaper, fPageAreas.thePaper);
  673.     fMarginRes = Point(((TPPrint) * fHPrint)->prInfo.iVRes, ((TPPrint) * fHPrint)->prInfo.iHRes);// read the new device resolution values 
  674.     fDeviceRes = fMarginRes;
  675.     fPrinterDev = ((TPPrint) * fHPrint)->prInfo.iDev;
  676.     RectToVRect(((TPPrint) * fHPrint)->prInfo.rPage, fPageAreas.theInk);
  677.     if (!fMinimalMargins)
  678.         fPageAreas.theMargins = VRect(IntMultiply((short)fPageAreas.theMargins.top, fMarginRes.v) / oldMarginRes.v, IntMultiply((short)fPageAreas.theMargins.left, fMarginRes.h) / oldMarginRes.h, IntMultiply((short)fPageAreas.theMargins.bottom, fMarginRes.v) / oldMarginRes.v, IntMultiply((short)fPageAreas.theMargins.right, fMarginRes.h) / oldMarginRes.h);
  679.  
  680.     aRect = fPageAreas.thePaper;
  681.     bRect = fPageAreas.theInk;
  682.     if ((aRect != oldPageAreas.thePaper) || (bRect != oldPageAreas.theInk) || (fDeviceRes != oldDevRes) || (oldPrinterDev == kNeverInitialized))
  683.     {
  684.         msgSent = FALSE;                        // something important to our projection model changed...
  685.         if (fDocument)
  686.             if (fDocument->fSharePrintInfo)
  687.             {
  688.                 fDocument->ForAllViewsDo(ItChanged, this);
  689.                 msgSent = TRUE;
  690.             }
  691.  
  692.         if (!msgSent)                            // didn't send msg to all views, current company included,
  693.         // so now we need to tell must my local view
  694.             fView->DoPrinterChanged();
  695.     }
  696. }
  697.  
  698. //--------------------------------------------------------------------------------------------------
  699. #pragma segment PrintImage
  700.  
  701. pascal void TStdPrintHandler::ChooseSpoolFile(Str255& spoolFileName,
  702.                                               short& spoolVRefNum,
  703.                                               long& pagesPerSubjob)
  704. {
  705.     spoolFileName = "";                            // Default choices tell MacPrint to use its
  706.     // standard choice algorithm
  707.     spoolVRefNum = 0;
  708.  
  709.     // Print Shop suggests attempting to print entire document.  If it
  710.     // runs out of space, then PerformPrinting will retry with a
  711.     // smaller number of pages.
  712.     pagesPerSubjob = MAXINT;
  713. }
  714.  
  715. //--------------------------------------------------------------------------------------------------
  716. #pragma segment PrintRes
  717.  
  718. pascal void TStdPrintHandler::ClosePrintShop(void)
  719. {
  720. #if qDebug
  721.     OSErr err;
  722. #endif
  723.  
  724.     PrClose();
  725. #if qDebug
  726.     err = PrError();                            // Now check for fresh error from MacPrint --
  727.     // only for debugging, since ChkPrintErr
  728.     // checks afresh in the real world
  729.     if (err != noErr)
  730.         cout << form("Error from MacPrint is: %1d\n", err);
  731. #endif
  732.  
  733. }
  734.  
  735. //--------------------------------------------------------------------------------------------------
  736. #pragma segment PrintRes
  737.  
  738. pascal void TStdPrintHandler::DoInMacPrint(pascal void(* WhatToDo)(void* staticLink),
  739.                                            void* staticLink)
  740. {
  741.     FailInfo fi;
  742.  
  743.     if (gCouldPrint)
  744.     {
  745.         PrSetError(noErr);                        // Clear printer-error flag 
  746.         if (!fi.CatchFailure())
  747.         {
  748.             this->OpenPrintShop();
  749.             (*WhatToDo)(staticLink);            // Do what needs to be done 
  750.             fi.Success();
  751.         }
  752.         else
  753.         {
  754.             this->ClosePrintShop();
  755.             SetPort(gWorkPort);                    // Might be left looking at a dead port 
  756.             gApplication->InvalidateFocus();
  757.             fi.ReSignal();
  758.         }
  759.         this->ClosePrintShop();
  760.         SetPort(gWorkPort);                        // Might be left looking at a dead port 
  761.         gApplication->InvalidateFocus();
  762.     }
  763.     // NB: if gCouldPrint is FALSE, DoInMacPrint is a no-op 
  764. }
  765.  
  766. //--------------------------------------------------------------------------------------------------
  767. #pragma segment PrintSelCommand
  768.  
  769. pascal void TStdPrintHandler::DoMenuCommand(CmdNumber aCmdNumber)// override 
  770. {
  771.     Boolean proceed;
  772.     TPrintCommand * aPrintCommand;
  773.  
  774.     switch (aCmdNumber)
  775.     {
  776.         case cPrint:
  777.             this->CheckPrinter();
  778.             if (this->PoseJobDialog())
  779.             {
  780.                 aPrintCommand = new TPrintCommand;
  781.                 aPrintCommand->IPrintCommand(aCmdNumber, this);
  782.                 this->PostCommand(aPrintCommand);
  783.             }
  784.             break;
  785.  
  786.         case cPrintOne:
  787.             this->CheckPrinter();
  788.             if (this->SetupPrintOne())
  789.             {
  790.                 aPrintCommand = new TPrintCommand;
  791.                 aPrintCommand->IPrintCommand(aCmdNumber, this);
  792.                 this->PostCommand(aPrintCommand);
  793.             }
  794.             break;
  795.  
  796.         case cPageSetup:
  797.             this->PosePageSetupDialog(proceed, TRUE);
  798.             break;
  799.  
  800.         case cShowBreaks:                        // Toggle state of "Show Breaks" 
  801.             fShowBreaks =!fShowBreaks;
  802.             this->InvalPageFeedback();                // force redraw of area the breaks did or will occupy
  803.             break;
  804.  
  805.         default:
  806.             inherited::DoMenuCommand(aCmdNumber);
  807.             break;
  808.     }
  809. }
  810.  
  811. //--------------------------------------------------------------------------------------------------
  812. #pragma segment PrintRes
  813.  
  814. pascal void TStdPrintHandler::DoSetupMenus(void)// override 
  815. {
  816.     inherited::DoSetupMenus();
  817.  
  818.     if (gCouldPrint && fView &&!MemSpaceIsLow())
  819.     {
  820.         Enable(cPrint, TRUE);
  821.         Enable(cPageSetup, TRUE);
  822.         Enable(cPrintOne, TRUE);
  823.     }
  824.  
  825.     EnableCheck(cShowBreaks, TRUE, fShowBreaks);
  826. }
  827.  
  828. //--------------------------------------------------------------------------------------------------
  829. #pragma segment PrintRes
  830. // A local class to help iterate over the list of handles and insert into a DescList
  831.  
  832. class CPageBreaks
  833. {
  834.     VHSelect& fOrthoVHS;
  835.     VHSelect& fVHS;
  836.     short& fWhichBreak;
  837.     const VRect& fViewArea;
  838.     TView* fView;
  839.  
  840. public:
  841.     CPageBreaks(VHSelect& theOrthoVHS,
  842.                 VHSelect& theVHS,
  843.                 short& whichBreak,
  844.                 const VRect& theViewArea,
  845.                 TView* theView) :
  846.         fOrthoVHS(theOrthoVHS),
  847.         fVHS(theVHS),
  848.         fWhichBreak(whichBreak),
  849.         fViewArea(theViewArea),
  850.         fView(theView)
  851.     {
  852.     }
  853.  
  854.     pascal Boolean DrawABreak(VCoordinate loc,
  855.                               Boolean automatic);
  856. };
  857.  
  858. #pragma segment PrintRes
  859. pascal Boolean CPageBreaks::DrawABreak(VCoordinate loc,
  860.                                        Boolean automatic)
  861. {
  862.     if (loc > fViewArea[botRight][fOrthoVHS])
  863.         return TRUE;
  864.     else
  865.     {
  866.         ++fWhichBreak;
  867.         if (loc > (fViewArea[topLeft][fOrthoVHS] - Point(gBreaksPenState.pnSize)[fOrthoVHS]))
  868.             fView->DoDrawPageBreak(fVHS, fWhichBreak, loc, automatic);
  869.         return FALSE;
  870.     }
  871. }
  872.  
  873. #pragma segment PrintRes
  874. // Draws page breaks and page numbers 
  875. pascal void TStdPrintHandler::DrawPrintFeedback(const VRect& area)// override 
  876. {
  877.     if (qDebug)
  878.         fView->AssumeFocused();
  879.     if (fShowBreaks || gDebugPrinting)
  880.     {
  881.         VHSelect vhs;
  882.         VHSelect orthoVHS;
  883.         short whichBreak = 0;
  884.         CPageBreaks aPageBreak(orthoVHS, vhs, whichBreak, area, fView);
  885.  
  886.         this->SetPrintExtent();                        // Make sure print extent is accurate before starting
  887. #if qDebug
  888.         if (gDebugPrinting)                        // Now draw Page numbers in the corners of pages, if desired
  889.         {
  890.             TextStyle pageNumStyle;
  891.  
  892.             SetTextStyle(pageNumStyle, applFont, bold, 9, gRGBBlack);
  893.             SetPortTextStyle(pageNumStyle);
  894.         }
  895. #endif
  896.  
  897.         SetPenState(gBreaksPenState);
  898.  
  899.         for (vhs = vSel; vhs <= hSel; ++vhs)
  900.         {
  901.             orthoVHS = gOrthogonal[vhs];
  902.             whichBreak = 0;
  903.             this->EachBreak(vhs, FALSE, (DoToBreakType) & CPageBreaks::DrawABreak, &aPageBreak);
  904.         }
  905.     }
  906. }
  907.  
  908. //--------------------------------------------------------------------------------------------------
  909. #pragma segment PrintRes
  910.  
  911. #if qDebug
  912. pascal void TStdPrintHandler::DrawPageBreak(VHSelect vhs,
  913.                                             long whichBreak,
  914.                                             VCoordinate loc,
  915.                                             Boolean)// override 
  916. #else
  917. pascal void TStdPrintHandler::DrawPageBreak(VHSelect vhs,
  918.                                             long/* whichBreak */,
  919.                                             VCoordinate loc,
  920.                                             Boolean)// multiple declarations to eliminate compiler warnings 
  921. #endif
  922.  
  923. {
  924.     VPoint vPt;
  925.     Point qdStartPt;
  926.     Point qdEndPt;
  927.  
  928.     vPt[gOrthogonal[vhs]] = loc;
  929.     vPt[vhs] = 0;
  930.     qdStartPt = fView->ViewToQDPt(vPt);
  931.     vPt[vhs] = fView->fSize[vhs] - Point(gBreaksPenState.pnSize)[vhs];
  932.     qdEndPt = fView->ViewToQDPt(vPt);
  933.  
  934.     if (fShowBreaks)
  935.     {
  936.         MoveTo(qdStartPt.h, qdStartPt.v);
  937.         LineTo(qdEndPt.h, qdEndPt.v);
  938.     }
  939.  
  940. #if qDebug
  941.     if (gDebugPrinting)
  942.         if (vhs == hSel)
  943.         {
  944.             VCoordinate hLoc;
  945.             Str255 aString;
  946.             FontInfo theFontInfo;
  947.             Rect theTextRect;
  948.  
  949.             for (long i = 0; i <= fPageStrips.v; ++i)
  950.             {
  951.                 if (i == 0)
  952.                     hLoc = 0;
  953.                 else
  954.                     this->GetBreakCoord(vSel, i, hLoc);
  955.  
  956.                 GetFontInfo(theFontInfo);
  957.  
  958.                 NumToString(this->StripToPage(whichBreak - 1, i), aString);
  959.                 // top computed based on the bottom - text height
  960.                 theTextRect = Rect(qdStartPt.v - 3 - theFontInfo.ascent, (short)hLoc + 3, qdStartPt.v - 3 + theFontInfo.descent, (short)hLoc + 3 + StringWidth(aString));
  961.                 MADrawString(aString, theTextRect, teFlushDefault);
  962.  
  963.                 NumToString(this->StripToPage(whichBreak, i), aString);
  964.                 // top computed based on the bottom - text height
  965.                 theTextRect = Rect(qdEndPt.v + 10 - theFontInfo.ascent, (short)hLoc + 3, qdEndPt.v + 10 + theFontInfo.descent, (short)hLoc + 3 + StringWidth(aString));
  966.                 MADrawString(aString, theTextRect, teFlushDefault);
  967.  
  968.                 NumToString(this->StripToPage(whichBreak - 1, i - 1), aString);
  969.                 // top computed based on the bottom - text height
  970.                 theTextRect = Rect(qdStartPt.v - 3 - theFontInfo.ascent, (short)hLoc - StringWidth(aString) - 3, qdStartPt.v - 3 + theFontInfo.descent, (short)hLoc - 3);
  971.                 MADrawString(aString, theTextRect, teFlushDefault);
  972.  
  973.                 NumToString(this->StripToPage(whichBreak, i - 1), aString);
  974.                 // top computed based on the bottom - text height
  975.                 theTextRect = Rect(qdEndPt.v + 10 - theFontInfo.ascent, (short)hLoc - StringWidth(aString) - 3, qdEndPt.v + 10 + theFontInfo.descent, (short)hLoc - 3);
  976.                 MADrawString(aString, theTextRect, teFlushDefault);
  977.             }
  978.         }
  979. #endif
  980.  
  981. }
  982.  
  983. //--------------------------------------------------------------------------------------------------
  984. #pragma segment PrintImage
  985.  
  986. pascal void TStdPrintHandler::DrawPageInterior(void)
  987. {
  988.     fView->DrawContents();                        // i.e., by default, the same code used for drawing on the screen
  989. }
  990.  
  991. //--------------------------------------------------------------------------------------------------
  992. #pragma segment PrintRes
  993.  
  994. pascal void TStdPrintHandler::EachBreak(VHSelect vhs,
  995.                                         Boolean includeLast,
  996.                                         pascal Boolean(* DoToBreak)(VCoordinate loc,
  997.                                                                     Boolean automatic,
  998.                                                                     void* staticLink),
  999.                                         void* staticLink)
  1000. {
  1001.     VCoordinate startLoc;
  1002.     VCoordinate endLoc;
  1003.     VCoordinate loc;
  1004.     Boolean automatic;
  1005.     Boolean done;
  1006.     VCoordinate prevBreak = 0;
  1007.  
  1008.     startLoc = fPrintExtent[topLeft][gOrthogonal[vhs]];
  1009.     endLoc = fPrintExtent[botRight][gOrthogonal[vhs]];
  1010.  
  1011.     loc = startLoc;
  1012.     automatic = TRUE;
  1013.     done = FALSE;
  1014.     while ((loc < endLoc) &&!done)
  1015.     {
  1016.         if (loc != startLoc)
  1017.             done = (*DoToBreak)(loc, automatic, staticLink);
  1018.         if (qDebug)
  1019.             prevBreak = loc;
  1020.  
  1021.         loc = fView->DoBreakFollowing(vhs, loc, automatic);
  1022.  
  1023.         if (qDebug && (loc <= prevBreak))
  1024.             ProgramBreak("thisBreak (loc) <= prevBreak");// Thanks much to Larry T. ! 
  1025.     }
  1026.  
  1027.     if (includeLast)
  1028.         (*DoToBreak)(loc, automatic, staticLink);
  1029. }
  1030.  
  1031. //--------------------------------------------------------------------------------------------------
  1032. #pragma segment PrintFields
  1033.  
  1034. pascal void TStdPrintHandler::Fields(TObject* obj)
  1035. {
  1036.     obj->DoToField("TStdPrintHandler", NULL, bClass);
  1037.     obj->DoToField("fPageAreas", NULL, bTitle);
  1038.     obj->DoToField("  thePaper", &fPageAreas.thePaper, bRect);
  1039.     obj->DoToField("  theInk", &fPageAreas.theInk, bRect);
  1040.     obj->DoToField("  theMargins", &fPageAreas.theMargins, bRect);
  1041.     obj->DoToField("  theInterior", &fPageAreas.theInterior, bRect);
  1042.     obj->DoToField("fPrintExtent", &fPrintExtent, bVRect);
  1043.     obj->DoToField("fFixedSizePages[h]", &fFixedSizePages[hSel], bBoolean);
  1044.     obj->DoToField("fFixedSizePages[v]", &fFixedSizePages[vSel], bBoolean);
  1045.     obj->DoToField("fHPrint", &fHPrint, bHandle);
  1046.     obj->DoToField("fPageStrips", &fPageStrips, bPoint);
  1047.     obj->DoToField("fStartPage", &fStartPage, bLongInt);
  1048.     obj->DoToField("fPrinterDev", &fPrinterDev, bLongInt);
  1049.     obj->DoToField("fLastPrinterName", &fLastPrinterName, bStringHandle);
  1050.     obj->DoToField("fPageDirection", &fPageDirection, bVHSelect);
  1051.     obj->DoToField("fShowBreaks", &fShowBreaks, bBoolean);
  1052.     obj->DoToField("fFinderSetup", &fFinderSetup, bBoolean);
  1053.     obj->DoToField("fFinderJobDialog", &fFinderJobDialog, bBoolean);
  1054.     obj->DoToField("fSquareDots", &fSquareDots, bBoolean);
  1055.     obj->DoToField("fMinimalMargins", &fMinimalMargins, bBoolean);
  1056.     obj->DoToField("fLastStrip", &fLastStrip, bPoint);
  1057.     obj->DoToField("fLastBreak", &fLastBreak, bVPoint);
  1058.     obj->DoToField("fViewedRect", &fViewedRect, bVRect);
  1059.     obj->DoToField("fMarginRes", &fMarginRes, bPoint);
  1060.     obj->DoToField("fPrintDialog", &fPrintDialog, bWindowPtr);// need a bDialogPtr 
  1061.  
  1062.     obj->DoToField("fPPrPort", NULL, bTitle);
  1063.     if (fPPrPort)
  1064.     {
  1065.         obj->DoToField("  gPort", &fPPrPort, bGrafPtr);
  1066.         obj->DoToField("  gProcs", &fPPrPort->gProcs, bQDProcs);
  1067.         obj->DoToField("  IGParam1", &fPPrPort->lGParam1, bLongInt);
  1068.         obj->DoToField("  IGParam2", &fPPrPort->lGParam2, bLongInt);
  1069.         obj->DoToField("  IGParam3", &fPPrPort->lGParam3, bLongInt);
  1070.         obj->DoToField("  IGParam4", &fPPrPort->lGParam4, bLongInt);
  1071.         obj->DoToField("  fOurPtr", &fPPrPort->fOurPtr, bBoolean);
  1072.         obj->DoToField("  fOurBits", &fPPrPort->fOurBits, bBoolean);
  1073.     }
  1074.     inherited::Fields(obj);
  1075. }
  1076.  
  1077. //--------------------------------------------------------------------------------------------------
  1078. #pragma segment PrintImage
  1079.  
  1080. pascal void TStdPrintHandler::FocusOnBorder(void)
  1081. {
  1082.     VRect rectToClipTo(fPageAreas.theInk);
  1083.     Rect qdRectToClipTo;
  1084.  
  1085.     // Only works for newer LaserWriter drivers 
  1086.     SetOrigin((short)fPageAreas.theInk.left, (short)fPageAreas.theInk.top);
  1087.     fView->ViewToQDRect(rectToClipTo, qdRectToClipTo);
  1088.     ClipRect(qdRectToClipTo);
  1089. }
  1090.  
  1091. //--------------------------------------------------------------------------------------------------
  1092. #pragma segment PrintImage
  1093.  
  1094. pascal void TStdPrintHandler::FocusOnInterior(void)// override 
  1095. {
  1096.     VRect rectToClip;
  1097.     VRect aRect;
  1098.     VPoint theOrigin;
  1099.     VPoint theVOrigin;
  1100.     VRect aVRect;
  1101.     Rect qdRectToClip;
  1102.  
  1103.     aRect = fPageAreas.theInk;
  1104.     theOrigin = fPageAreas.theInk[topLeft];
  1105.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1106.         if (fView->fSize[vhs] > kMaxCoord)
  1107.             theVOrigin[vhs] = gPageOffset[vhs];
  1108.         else
  1109.         {
  1110.             theVOrigin[vhs] = 0;
  1111.             theOrigin[vhs] = theOrigin[vhs] + gPageOffset[vhs];
  1112.             aRect[topLeft][vhs] = aRect[topLeft][vhs] + gPageOffset[vhs];
  1113.             aRect[botRight][vhs] = aRect[botRight][vhs] + gPageOffset[vhs];
  1114.         }
  1115.     SetOrigin((short)theOrigin.h, (short)theOrigin.v);
  1116.     fView->fViewToQDOffset = theVOrigin;
  1117.  
  1118.     // Clip the page to the intersection of the visible part of the view and the
  1119.     // printable area of the page.  Note that in some cases (e.g., a WYSIWYG
  1120.     // word processor which showed the complete page margin) parts of
  1121.     // the interior might lie outside theInk.  We must clip to theInk to
  1122.     // avoid slowing down PostScript printers.
  1123.     rectToClip = fViewedRect;
  1124.     SectVRect(rectToClip, aRect, rectToClip);
  1125.     fView->ViewToQDRect(rectToClip, qdRectToClip);
  1126.     ClipRect(qdRectToClip);
  1127. }
  1128.  
  1129. //--------------------------------------------------------------------------------------------------
  1130. #pragma segment PrintRes
  1131.  
  1132. pascal void TStdPrintHandler::GetBreakCoord(VHSelect vhs,
  1133.                                             long whichBreak,
  1134.                                             VCoordinate& loc)
  1135. {
  1136.     Boolean automatic;
  1137.     long startBreak;
  1138.     VHSelect orthoVHS;
  1139.     VCoordinate prevBreak = 0;
  1140.  
  1141.  
  1142.     orthoVHS = gOrthogonal[vhs];
  1143.     if (fFixedSizePages[orthoVHS])
  1144.         loc = fPrintExtent[topLeft][orthoVHS] + fViewPerPage[orthoVHS] * whichBreak;
  1145.     else if (whichBreak == fLastStrip[vhs])
  1146.         loc = fLastBreak[vhs];
  1147.     else
  1148.     {
  1149.         if (whichBreak > fLastStrip[vhs])
  1150.         {
  1151.             startBreak = fLastStrip[vhs] + 1;
  1152.             loc = fLastBreak[vhs];
  1153.         }
  1154.         else
  1155.         {
  1156.             startBreak = 1;
  1157.             loc = fPrintExtent[topLeft][gOrthogonal[vhs]];
  1158.         }
  1159.  
  1160.         for (long i = startBreak; i <= whichBreak; ++i)
  1161.         {
  1162.             if (qDebug)
  1163.                 prevBreak = loc;
  1164.  
  1165.             loc = fView->DoBreakFollowing(vhs, loc, automatic);// ??? error handling??? 
  1166.  
  1167.             if (qDebug && (loc <= prevBreak))
  1168.                 ProgramBreak("thisBreak (loc) <= prevBreak");
  1169.         }
  1170.     }
  1171.     loc = Min(loc, fPrintExtent[botRight][orthoVHS]);
  1172.  
  1173.     fLastStrip[vhs] = whichBreak;
  1174.     fLastBreak[vhs] = loc;
  1175. }
  1176.  
  1177. //--------------------------------------------------------------------------------------------------
  1178. #pragma segment PrintActual
  1179.  
  1180. pascal void TStdPrintHandler::GetDocName(Str255& docName)
  1181. {
  1182.     TView * aView;
  1183.  
  1184.     if (fDocument)
  1185.         fDocument->GetTitle(docName);
  1186.     if (docName.IsEmpty())
  1187.     {
  1188.         aView = fView->GetRootView();
  1189.         if (aView && aView->IsMemberClass(GetClassIDFromName("TWindow")))
  1190.             ((TWindow *)aView)->GetTitle(docName);
  1191.     }
  1192. #if qDebug
  1193.     if (docName.IsEmpty())
  1194.         ProgramBreak("GetDocName can''t get a document or window name");
  1195. #endif
  1196.  
  1197. }
  1198.  
  1199. //--------------------------------------------------------------------------------------------------
  1200. #pragma segment PrintMain
  1201.  
  1202. pascal Handle TStdPrintHandler::GetPrintInfo(void)
  1203. {
  1204.     return fHPrint;
  1205. }
  1206.  
  1207. //--------------------------------------------------------------------------------------------------
  1208. #pragma segment PrintNonRes
  1209.  
  1210. pascal void TStdPrintHandler::InstallMargins(const VRect& newMargins,
  1211.                                              Boolean areMinimalMargins)
  1212. {
  1213.     fMinimalMargins = areMinimalMargins;
  1214.  
  1215.     if (fMinimalMargins)
  1216.     {
  1217.         fPageAreas.theMargins = fPageAreas.theInk;
  1218.         fPageAreas.thePaper[topLeft] -= fPageAreas.theMargins[topLeft];
  1219.         fPageAreas.thePaper[botRight] -= fPageAreas.theMargins[botRight];
  1220.         fPageAreas.theInterior = fPageAreas.theInk;
  1221.     }
  1222.     else
  1223.     {
  1224.         fPageAreas.theMargins = newMargins;
  1225.         fPageAreas.theInterior = fPageAreas.thePaper;
  1226.         fPageAreas.theMargins[topLeft] += fPageAreas.theInterior[topLeft];
  1227.         fPageAreas.theMargins[botRight] += fPageAreas.theInterior[botRight];
  1228.     }
  1229. }
  1230.  
  1231. //--------------------------------------------------------------------------------------------------
  1232. #pragma segment PrintNonRes
  1233.  
  1234. pascal void TStdPrintHandler::InvalPageFeedback(void)
  1235. {
  1236.     if (this->ShowsOnScreen())
  1237.         fView->ForceRedraw();
  1238. }
  1239.  
  1240. //--------------------------------------------------------------------------------------------------
  1241. #pragma segment PrintNonRes
  1242.  
  1243. pascal void TStdPrintHandler::LocatePageInterior(long,
  1244.                                                  VPoint& loc)// override 
  1245. {
  1246.     loc = fPageAreas.thePaper[topLeft];
  1247.     fPageAreas.theMargins[topLeft] += loc;
  1248. }
  1249.  
  1250. //--------------------------------------------------------------------------------------------------
  1251. #pragma segment PrintActual
  1252.  
  1253. pascal long TStdPrintHandler::MaxPageNumber(void)// override 
  1254.  
  1255. {
  1256.     return fStartPage + (fPageStrips.v * fPageStrips.h) - 1;
  1257. }
  1258.  
  1259. //--------------------------------------------------------------------------------------------------
  1260. #pragma segment PrintActual
  1261.  
  1262. pascal void TStdPrintHandler::OneSubJob(long subjobFirstPage,
  1263.                                         long subjobLastPage,
  1264.                                         Boolean justSpool,
  1265.                                         Boolean,
  1266.                                         Boolean& ranOutOfSpace,
  1267.                                         long& lastPageTried,
  1268.                                         Boolean& proceed)
  1269. {
  1270.     long noOfCopies;
  1271.     OSErr err;
  1272.     TPrJob & printJob = ((TPPrint) * fHPrint)->prJob;
  1273.     FailInfo fi;
  1274.  
  1275. #if qDebug
  1276.     if (gDebugPrinting)
  1277.         cout << form("OneSubJob entered for pages %1d through %1d, proceed=", subjobFirstPage, subjobLastPage) << proceed << "\n";
  1278. #endif
  1279.  
  1280.     ranOutOfSpace = FALSE;
  1281.     lastPageTried = subjobFirstPage - 1;
  1282.  
  1283.     printJob.iFstPage = 1;
  1284.     printJob.iLstPage = (short)(subjobLastPage - subjobFirstPage + 1);
  1285.  
  1286.     if (printJob.bJDocLoop == bSpoolLoop)
  1287.         noOfCopies = 1;
  1288.     else
  1289.         noOfCopies = printJob.iCopies;
  1290.  
  1291.     fPPrPort = PrOpenDoc((THPrint)fHPrint, NULL, NULL);
  1292.     // ??? need to allow/encourage app to supply nonNil args? 
  1293.     this->ChkPrintErr(err, proceed, ranOutOfSpace);
  1294.     gCurrPrintHandler = this;
  1295.  
  1296.     if (proceed)
  1297.     {
  1298.         fView->InvalidateFocus();
  1299.         fView->UpdateCoordinates();
  1300.         gPrinting = TRUE;
  1301.         SetPort((GrafPtr)fPPrPort);
  1302.         fView->BeInPort((GrafPtr)fPPrPort);
  1303.  
  1304.         gPrinting = TRUE;
  1305.         if (!fView->Focus())
  1306.         {
  1307. #if qDebug
  1308.             ProgramBreak("Can''t focus view while printing");
  1309. #endif
  1310.  
  1311.         }
  1312.         for (long pass = 1; pass <= noOfCopies; ++pass)
  1313.             for (long aPageNumber = subjobFirstPage; aPageNumber <= subjobLastPage; ++aPageNumber)
  1314.                 if (proceed)
  1315.                 {
  1316.                     lastPageTried = aPageNumber;
  1317.                     if (!fi.CatchFailure())
  1318.                     {
  1319.                         this->PrintPage(aPageNumber);
  1320.                         fi.Success();
  1321.                     }
  1322.                     else
  1323.                     {
  1324.                         proceed = FALSE;
  1325.                         err = fi.error;            // pass along client's error code Why???
  1326.                     }
  1327.                     this->ChkPrintErr(err, proceed, ranOutOfSpace);
  1328.                 }
  1329.         gPrinting = FALSE;
  1330.         fView->InvalidateFocus();
  1331.         fView->UpdateCoordinates();
  1332.         fView->BeInPort(fView->GetGrafPort());
  1333.     }
  1334.  
  1335.     gCurrPrintHandler = NULL;
  1336.     PrCloseDoc(fPPrPort);                        // This will close the port! 
  1337.     SetPort(gWorkPort);
  1338.     this->ChkPrintErr(err, proceed, ranOutOfSpace);
  1339.  
  1340.     if (ranOutOfSpace)
  1341.         return;
  1342.     else if (proceed)
  1343.     {
  1344.         if (printJob.bJDocLoop == bSpoolLoop)
  1345.             if (!justSpool)
  1346.                 this->PrintSpoolFile(fHPrint, err, proceed);
  1347.     }
  1348.     if (!proceed)
  1349.         if (err != iPrAbort)
  1350.             Failure(err, 0);
  1351. }
  1352.  
  1353. //--------------------------------------------------------------------------------------------------
  1354. #pragma segment PrintRes
  1355.  
  1356. pascal void TStdPrintHandler::OpenPrintShop(void)
  1357. {
  1358.     OSErr err;
  1359.  
  1360.     PrOpen();                                    // Open the print shop 
  1361.     err = PrError();                            // Get code 
  1362.     if (err != noErr)
  1363.     {
  1364.         if ((err == fnfErr) || (err == resFNotFound))
  1365.             err = errNoPrintDrvr;
  1366.         Failure(err, 0);
  1367.     }
  1368. }
  1369.  
  1370. //--------------------------------------------------------------------------------------------------
  1371. #pragma segment PrintRes
  1372.  
  1373. pascal VPoint TStdPrintHandler::PageToStrip(long pageNumber)
  1374. {
  1375.     long normalizedPageNum;
  1376.     VHSelect ortho;
  1377.     VPoint strip;
  1378.  
  1379.     normalizedPageNum = pageNumber - fStartPage + 1;
  1380.  
  1381.     ortho = gOrthogonal[fPageDirection];
  1382.  
  1383.     strip[ortho] = (normalizedPageNum - 1) / fPageStrips[ortho];
  1384.     strip[fPageDirection] = normalizedPageNum - ((strip[ortho]) * fPageStrips[ortho]) - 1;
  1385.  
  1386.     return strip;
  1387. }
  1388.  
  1389. //--------------------------------------------------------------------------------------------------
  1390. #pragma segment PrintRes
  1391.  
  1392. // !!! Need to test this! 
  1393. pascal VPoint TStdPrintHandler::PointToPageStrip(const VPoint& pointInView)
  1394. {
  1395.     long loc;
  1396.     Boolean automatic;
  1397.     VPoint pageStrip;
  1398.     VCoordinate prevBreak = 0;
  1399.  
  1400.  
  1401.     for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1402.         if (fFixedSizePages[vhs])
  1403.             pageStrip[vhs] = (pointInView[vhs] / fViewPerPage[vhs]) + 1;
  1404.         else
  1405.         {
  1406.             pageStrip[vhs] = 1;
  1407.             loc = fPrintExtent[topLeft][vhs];    // ??? or orthogonal? 
  1408.             while (pointInView[vhs] > loc)
  1409.                 // ??? or orthogonal? 
  1410.                 {
  1411.                     if (qDebug)
  1412.                         prevBreak = loc;
  1413.  
  1414.                     loc = fView->DoBreakFollowing(vhs, loc, automatic);
  1415.  
  1416.                     if (qDebug && (loc <= prevBreak))
  1417.                         ProgramBreak("thisBreak (loc) <= prevBreak");
  1418.  
  1419.                     pageStrip[vhs]++;            // ??? Check the pascal.  This may be wrong. !!!
  1420.                 }
  1421.         }
  1422.     return pageStrip;
  1423. }
  1424.  
  1425. //--------------------------------------------------------------------------------------------------
  1426. #pragma segment PrintActual
  1427.  
  1428. class CPrintDialogs
  1429. {
  1430.     Boolean& fResult;
  1431.     Handle& fHPrint;
  1432.  
  1433. public:
  1434.     CPrintDialogs(Boolean& proceed,
  1435.                   Handle& printHandle) :
  1436.         fResult(proceed),
  1437.         fHPrint(printHandle)
  1438.     {
  1439.     }
  1440.  
  1441.     pascal void CallJobDialog(void);
  1442.  
  1443.     pascal void CallStyleDialog(void);
  1444.  
  1445.     pascal void CallPrValidate(void);
  1446. };
  1447.  
  1448. #pragma segment PrintActual
  1449. pascal void CPrintDialogs::CallJobDialog(void)
  1450. {
  1451.     SetCursor(qd.arrow);
  1452.     if (gApplication)
  1453.         gApplication->InvalidateMouseRegions();
  1454.  
  1455.     fResult = PrJobDialog((THPrint)fHPrint);
  1456. }
  1457.  
  1458. #pragma segment PrintActual
  1459. pascal void CPrintDialogs::CallStyleDialog(void)
  1460. {
  1461.     SetCursor(qd.arrow);
  1462.     if (gApplication != NULL)
  1463.         gApplication->InvalidateMouseRegions();
  1464.  
  1465.     fResult = PrStlDialog((THPrint)fHPrint);
  1466. }
  1467.  
  1468. #pragma segment PrintActual
  1469. pascal void CPrintDialogs::CallPrValidate(void)
  1470. {
  1471.     fResult = PrValidate((THPrint)fHPrint);
  1472. }
  1473.  
  1474. #pragma segment PrintActual
  1475. pascal Boolean TStdPrintHandler::PoseJobDialog(void)
  1476. {
  1477.     Boolean b;
  1478.     Boolean proceed;
  1479.     OSErr err;
  1480.     TPrJob & printJob = ((TPPrint) * fHPrint)->prJob;
  1481.     CPrintDialogs aJobDialog(proceed, fHPrint);
  1482.  
  1483.     proceed = TRUE;
  1484.     // PrepareForDialog; 
  1485.     this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallJobDialog, &aJobDialog);
  1486.     this->ChkPrintErr(err, proceed, b);
  1487.     // Rectify the range as a public service if needed
  1488.     if (printJob.iFstPage > printJob.iLstPage)
  1489.     {
  1490.         short temp;
  1491.  
  1492.         temp = printJob.iLstPage;
  1493.         printJob.iLstPage = printJob.iFstPage;
  1494.         printJob.iFstPage = temp;
  1495.     }
  1496.     gApplication->UpdateAllWindows();
  1497.     return proceed;
  1498. }
  1499.  
  1500. //--------------------------------------------------------------------------------------------------
  1501. #pragma segment PrintActual
  1502. // Needs to be here because it may be called from Print
  1503.  
  1504. pascal void TStdPrintHandler::PosePageSetupDialog(Boolean& proceed,
  1505.                                                   Boolean isUndoable)
  1506. {
  1507.     Boolean react;
  1508.     TPrintStyleChangeCommand * aPrintStyleChangeCommand;
  1509.     CPrintDialogs aPageSetupDialog(react, fHPrint);
  1510.  
  1511.     react = FALSE;                                // in case MacPrint code not accessible 
  1512.     if (!isUndoable)
  1513.     {
  1514.         // PrepareForDialog; 
  1515.         this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallStyleDialog, &aPageSetupDialog);
  1516.         if (react)
  1517.             this->CheckPrinter();
  1518.     }
  1519.     else
  1520.     {
  1521.         // Must setup command before putting up page setup dialog because the
  1522.         // command records the current print record to make it undoable.
  1523.         aPrintStyleChangeCommand = new TPrintStyleChangeCommand;
  1524.         aPrintStyleChangeCommand->IPrintStyleChangeCommand(this);
  1525.  
  1526.         // Put up the Page Setup Dialog 
  1527.         this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallStyleDialog, &aPageSetupDialog);
  1528.         if (react)                                // User specified a change 
  1529.         {
  1530.             BlockMove((Ptr) * fHPrint, (Ptr) * (aPrintStyleChangeCommand->fNewHPrint), sizeof(TPrint));
  1531.             this->PostCommand(aPrintStyleChangeCommand);
  1532.         }
  1533.         else                                    // User did not specify a change 
  1534.             aPrintStyleChangeCommand = (TPrintStyleChangeCommand *)FreeIfObject(aPrintStyleChangeCommand);
  1535.     }
  1536.     proceed = react;
  1537. }
  1538.  
  1539. //--------------------------------------------------------------------------------------------------
  1540. #pragma segment PrintActual
  1541.  
  1542. pascal void TStdPrintHandler::PosePrintDialog(void)
  1543. {
  1544.     short dlgNumber;
  1545.     DialogTHndl dlogTemplate;
  1546.     Str255 docName;
  1547.     short itemNo;
  1548.     Handle theItem;
  1549.     short itemType;
  1550.     Rect box;
  1551.     Str255 itemText;
  1552.     short preDocName,
  1553.      constTitle;
  1554.  
  1555.     /*### need to determine if multiple file printing is in process
  1556.       if (gFinderPrinting)
  1557.       {
  1558.       dlgNumber = phFinderPrintDialog;
  1559.       itemNo = 3;
  1560.       }
  1561.       else
  1562.       {
  1563.       dlgNumber = phSpoolPrintDialog;
  1564.       itemNo = 2;
  1565.       }
  1566.     */
  1567.     dlgNumber = phSpoolPrintDialog;
  1568.     itemNo = 2;
  1569.  
  1570.     // Can't use GetNewCenteredDialog because vertically centering the dialog may cause it
  1571.     // to interfere with the Print Manager's status windows.  Therefore, leave the vertical
  1572.     // location of the dialog fixed.
  1573.  
  1574.     SetCursor(qd.arrow);
  1575.     gApplication->InvalidateMouseRegions();
  1576.     dlogTemplate = (DialogTHndl)GetResource('DLOG', dlgNumber);
  1577.     if (dlogTemplate)
  1578.     {
  1579.         CenterRectOnScreen((*dlogTemplate)->boundsRect, TRUE, FALSE, FALSE);
  1580.         fPrintDialog = GetNewDialog(dlgNumber, (Ptr)NULL, (WindowPtr) - 1);
  1581.         FailNIL(fPrintDialog);
  1582.     }
  1583.     else
  1584.     {
  1585. #if qDebug
  1586.         cout << "You may have forgotten to include Printing.rsrc in your .r file…\n";
  1587.         ProgramBreak("The print job dialog resource can''t be found.");
  1588. #endif
  1589.  
  1590.         FailNILResource((Handle)dlogTemplate);
  1591.     }
  1592.  
  1593.     // Substitute the document name for '<<!=>>' in 'Document “<<!=>>” is being printed'.
  1594.     // ParamText would be a lot simpler, but the Print Mgr. also uses ParamText, and
  1595.     // the substitution doesn't happen until draw time.
  1596.     this->GetDocName(docName);
  1597.     GetDItem(fPrintDialog, itemNo, itemType, theItem, box);
  1598.     if (theItem)
  1599.     {
  1600.         GetIText(theItem, itemText);
  1601.         if (ParseTitleTemplate(itemText, preDocName, constTitle) && SubstituteInTitle(itemText, docName, preDocName, constTitle))
  1602.             SetIText(theItem, itemText);
  1603.     }
  1604.  
  1605.     ((TPPrint) * fHPrint)->prJob.pIdleProc = &IdleProcForTStdPrintHandler;
  1606.     SetWTitle(fPrintDialog, docName);            // In case Print Mgr. needs it. 
  1607.     DrawDialog(fPrintDialog);
  1608. }
  1609.  
  1610. //--------------------------------------------------------------------------------------------------
  1611. // ???Was in PrintActual.  Doesn't really belong in this segment,
  1612. //but can get unloaded during Finder printing otherwise.
  1613. #pragma segment PrintRes
  1614.  
  1615. pascal void TStdPrintHandler::Print(CmdNumber itsCmdNumber,
  1616.                                     Boolean& proceed)// override 
  1617. {
  1618.     FailInfo fi;
  1619.  
  1620.     gCancelAllPrinting = FALSE;
  1621.  
  1622.     this->SetPrintExtent();                            // Make sure we've got the right area. 
  1623.  
  1624.     if (!fi.CatchFailure())
  1625.     {
  1626.         if (gCouldPrint)
  1627.         {
  1628.             long firstPage;
  1629.             long lastPage;
  1630.             OSErr err;
  1631.             Str255 spoolFileName;
  1632.             short spoolVRefNum;
  1633.             TPrJob aPrJob = ((TPPrint) * fHPrint)->prJob;
  1634.             long totalPages;
  1635.             long lastPrinted;
  1636.             long lastAttempted;
  1637.             long pagesPerSubjob;
  1638.             long firstSubjobPage;
  1639.             Boolean proceed = TRUE;
  1640.             Boolean ranOutOfSpace = FALSE;
  1641.             Boolean spoolMethod;
  1642.             Boolean justSpool = (itsCmdNumber == cPrintToFile);
  1643.             VPoint pageStrips;
  1644.             FailInfo fi;
  1645.  
  1646.             PrSetError(noErr);                    // Clear printer-error flag 
  1647.             this->OpenPrintShop();
  1648.             gJobPrintHandler = this;            // be visible to the idleProc 
  1649.             fView->DoCalcPageStrips(pageStrips);
  1650.             fPageStrips = pageStrips;
  1651.  
  1652.             firstPage = Max(aPrJob.iFstPage, fStartPage);
  1653.             lastPage = Min(aPrJob.iLstPage, this->MaxPageNumber());
  1654.  
  1655.             if (lastPage < firstPage)
  1656.                 err = Alert(phNoPages, NULL);
  1657.             else
  1658.             {
  1659.                 totalPages = lastPage - firstPage + 1;
  1660.                 spoolMethod = (aPrJob.bJDocLoop == bSpoolLoop);
  1661.                 if (spoolMethod)
  1662.                 {
  1663.                     this->ChooseSpoolFile(spoolFileName, spoolVRefNum, pagesPerSubjob);
  1664.                     // if justSpool is true, then the spool filename and vRefNum will already
  1665.                     // have been stuffed into the prJob record before this method is called
  1666.                     if (!justSpool)
  1667.                     {
  1668.                         if (!spoolFileName.IsEmpty())
  1669.                         {
  1670.                             aPrJob.pFileName = &spoolFileName;
  1671.                             aPrJob.iFileVol = spoolVRefNum;
  1672.                         }
  1673.                     }
  1674.                 }
  1675.                 else
  1676.                     pagesPerSubjob = MAXINT;
  1677.  
  1678.                 lastPrinted = firstPage - 1;
  1679.  
  1680.                 pagesPerSubjob = Min(pagesPerSubjob, totalPages);
  1681.                 this->PosePrintDialog();
  1682.  
  1683.                 if (!fi.CatchFailure())
  1684.                 {
  1685.                     do
  1686.                     {
  1687.                         firstSubjobPage = lastPrinted + 1;
  1688.                         this->OneSubJob(firstSubjobPage, firstSubjobPage + pagesPerSubjob - 1, justSpool, (pagesPerSubjob < totalPages), ranOutOfSpace, lastAttempted, proceed);
  1689.                         if (proceed)
  1690.                             lastPrinted = lastAttempted;
  1691.                         if (ranOutOfSpace)
  1692.                         {
  1693.                             pagesPerSubjob = lastAttempted - 1 - firstSubjobPage;
  1694.                             proceed = TRUE;
  1695.                         }
  1696.                     } while ((lastPrinted == lastPage) || (pagesPerSubjob < 1) ||!proceed);
  1697.  
  1698.                     if (pagesPerSubjob < 1)
  1699.                         Failure(errSpooling, 0);
  1700.                     fi.Success();
  1701.                 }
  1702.                 else
  1703.                 {
  1704.                     this->BanishPrintDialog();
  1705.                     fi.ReSignal();
  1706.                 }
  1707.                 this->BanishPrintDialog();            // having removed, put back here, unsure if exactly right
  1708.             }                                    // if there are pages within requested range
  1709.             gJobPrintHandler = NULL;            // out damned spot 
  1710.         }
  1711.         this->ClosePrintShop();
  1712.         SetPort(gWorkPort);                        // Might be left looking at a dead port 
  1713.         gApplication->InvalidateFocus();
  1714.         fi.Success();
  1715.     }
  1716.     else
  1717.     {
  1718.         this->ClosePrintShop();
  1719.         SetPort(gWorkPort);                        // Might be left looking at a dead port 
  1720.         gApplication->InvalidateFocus();
  1721.  
  1722.         // Certain Print Manager errors should not result in any alert,
  1723.         // since the Print Manager will have already put one up.
  1724.         if ((fi.error >= -8160) && (fi.error <= -8150))
  1725.             Failure(0, msgPrintFailed);
  1726.         if (fi.message == 0)
  1727.             this->GetDocName(gErrorParm3);
  1728.         FailNewMessage(fi.error, fi.message, msgPrintFailed);
  1729.         fi.ReSignal();
  1730.     }
  1731.     proceed =!gCancelAllPrinting;
  1732. }
  1733.  
  1734. //--------------------------------------------------------------------------------------------------
  1735. #pragma segment PrintNonRes
  1736.  
  1737. pascal void TStdPrintHandler::PrinterChanged(void)// override 
  1738. {
  1739.     fView->DoPagination();
  1740. }
  1741.  
  1742. //--------------------------------------------------------------------------------------------------
  1743. #pragma segment PrintImage
  1744.  
  1745. pascal void TStdPrintHandler::PrintPage(long aPageNumber)// Print a single page 
  1746. {
  1747.     FailInfo fi;
  1748.  
  1749.     this->SetPage(aPageNumber);                        // gets gPage set up correctly for coordinate transformations
  1750.     if (!fi.CatchFailure())
  1751.     {
  1752. #if qDebug
  1753.         GrafPtr aPort;
  1754. #endif
  1755.  
  1756.         PrOpenPage(fPPrPort, NULL);
  1757.         FailOSErr(PrError());
  1758.         this->FocusOnInterior();
  1759.         this->DrawPageInterior();
  1760. #if qDebug
  1761.         GetPort(aPort);
  1762.         if (aPort != ((GrafPtr) fPPrPort))
  1763.             ProgramBreak("The view''s DrawPageInterior method changed the grafPort");
  1764. #endif
  1765.  
  1766.         FailOSErr(PrError());
  1767.         this->FocusOnBorder();
  1768.         this->AdornPage();
  1769.         FailOSErr(PrError());
  1770.         fi.Success();
  1771.     }
  1772.     else
  1773.     {
  1774.         PrClosePage(fPPrPort);
  1775.         fi.ReSignal();
  1776.     }
  1777.     PrClosePage(fPPrPort);
  1778. }
  1779.  
  1780. //--------------------------------------------------------------------------------------------------
  1781. #pragma segment PrintNonRes
  1782.  
  1783. // Called from fView.DoPagination. 
  1784. pascal void TStdPrintHandler::RedoPageBreaks(void)// override 
  1785. {
  1786.     Boolean worryAboutBreaks;
  1787.     VPoint oldViewPerPage,  viewPerPage;
  1788.     VPoint pageStrips;
  1789.     VRect newInterior,  oldInterior;
  1790.  
  1791.     worryAboutBreaks = (fView->GetGrafPort()) && gInitialized && (fShowBreaks || gDebugPrinting);
  1792.  
  1793.     if (worryAboutBreaks)
  1794.         this->InvalPageFeedback();                    // invalidate old page breaks, if relevant 
  1795.  
  1796.     this->SetPrintExtent();
  1797.     oldInterior = fPageAreas.theInterior;
  1798.     oldViewPerPage = fViewPerPage;
  1799.     this->SetMargins();
  1800.  
  1801.     // computes view per page from papersize, printer resolution, margins desired, view resolution,
  1802.     //and, if desired, other factors such as printable rectangle of page and font metrics in the
  1803.     //printer space
  1804.     fView->DoCalcViewPerPage(viewPerPage);
  1805.     fViewPerPage = viewPerPage;
  1806.     this->SetPageInterior(kUsualPages);
  1807.     newInterior = fPageAreas.theInterior;
  1808.  
  1809. #if qDebug
  1810.     if (gDebugPrinting)
  1811.         if (oldInterior != newInterior)
  1812.             ProgramBreak("Setting new interior");
  1813. #endif
  1814.  
  1815.     if (oldInterior != newInterior)
  1816.         fView->PageInteriorChanged(newInterior);
  1817.  
  1818. #if qDebug
  1819.     if (gDebugPrinting)
  1820.         if (oldViewPerPage != viewPerPage)
  1821.             ProgramBreak("Setting new view per page");
  1822. #endif
  1823.  
  1824.     if ((oldInterior != newInterior) || (oldViewPerPage != viewPerPage))
  1825.         fView->AdjustSize();
  1826.  
  1827.     fView->DoCalcPageStrips(pageStrips);
  1828.     fPageStrips = pageStrips;
  1829.  
  1830.     if (worryAboutBreaks)
  1831.         this->InvalPageFeedback();                    // force redraw of new page breaks, if relevant
  1832. }
  1833.  
  1834.     //--------------------------------------------------------------------------------------------------
  1835. #pragma segment PrintNonRes
  1836.  
  1837.     pascal void CallPrintDefault(void* staticLink)
  1838.     {
  1839.         PrintDefault(*((THPrint *)staticLink));
  1840.     }
  1841.  
  1842.  
  1843.     pascal void TStdPrintHandler::Reset(void)
  1844.     {
  1845.         THPrint anHPrint = (THPrint)fHPrint;
  1846.         Boolean didChange;
  1847.         Boolean inited = FALSE;
  1848.         FailInfo fi;
  1849.  
  1850.         if (anHPrint)
  1851.         {
  1852.             if (gCouldPrint)
  1853.             {
  1854.                 if (!fi.CatchFailure())
  1855.                 {
  1856.                     TXWord printerFlags;
  1857.  
  1858.                     this->DoInMacPrint(CallPrintDefault, &anHPrint);
  1859.                     if (fSquareDots)
  1860.                     {
  1861.                         printerFlags.iO = ((TPPrint) * fHPrint)->prStl.wDev;
  1862.                         if (printerFlags.byteVal.b1 == 1)// 1 == bDevCItoh => ImageWriter 
  1863.                         {
  1864.                             // Set the square-pixel flag in the print record, then
  1865.                             // ensure we didn't corrupt it.
  1866.                             printerFlags.boolVal.f2 = TRUE;
  1867.                             this->ValidatePrintRecord(didChange);
  1868.                         }
  1869.                     }
  1870.                     inited = TRUE;
  1871.                     fi.Success();
  1872.                 }
  1873.             }
  1874.             // MacPrint code unavailable, but we want some plausible things
  1875.             // anyway - set up for Portrait Tall Adj.
  1876.             // ??? Replace the following expensive stuffing code with StuffHex
  1877.             // calls or a GetResource or some such, later
  1878.             if (!(gCouldPrint && inited))
  1879.             {
  1880.                 (*anHPrint)->iPrVersion = 0;    // something invalid 
  1881.  
  1882.                 (*anHPrint)->prInfo.iHRes = 72;
  1883.                 (*anHPrint)->prInfo.iVRes = 72;
  1884.                 (*anHPrint)->prInfo.rPage = Rect(0, 0, 752, 576);// must have its top left & (0,0)
  1885.  
  1886.                 (*anHPrint)->rPaper = Rect(-36, -18, 756, 594);
  1887.                 (*anHPrint)->prStl.iPageV = 1320;// 11 inches in 120th of an inch 
  1888.                 (*anHPrint)->prStl.iPageH = 1020;// 8.5 inches in 120th of an inch 
  1889.             }
  1890.         }
  1891.     }
  1892.  
  1893.     //--------------------------------------------------------------------------------------------------
  1894. #pragma segment PrintNonRes
  1895.  
  1896.     pascal void TStdPrintHandler::SetPrintExtent(void)
  1897.     {
  1898.         VRect printExtent;
  1899.  
  1900.         fView->GetPrintExtent(printExtent);
  1901.         // Make sure the bottom or right is not smaller than the top or left.
  1902.         // This can happen when views are being created and before the window
  1903.         // has been resized to its actual size.
  1904.         printExtent.bottom = Max(printExtent.bottom, printExtent.top);
  1905.         printExtent.right = Max(printExtent.right, printExtent.left);
  1906.         fPrintExtent = printExtent;
  1907.     }
  1908.  
  1909.     //--------------------------------------------------------------------------------------------------
  1910. #pragma segment PrintOpen
  1911.  
  1912.     pascal void TStdPrintHandler::SetDefaultPrintInfo(void)
  1913.     {
  1914.         Boolean didChange;
  1915.         Boolean wantValidate = FALSE;
  1916.         Boolean haveHPrint = FALSE;
  1917.  
  1918.         fHPrint = DisposeIfHandle(fHPrint);
  1919.  
  1920.         if (fView)
  1921.         {
  1922.             if (fDocument && (fDocument->fSharePrintInfo && fDocument->fPrintInfo))
  1923.             {
  1924.                 fHPrint = fDocument->fPrintInfo;
  1925.                 haveHPrint = TRUE;
  1926.             }
  1927.         }
  1928.  
  1929.         if (haveHPrint)
  1930.             wantValidate = TRUE;
  1931.         else
  1932.         {
  1933.             fHPrint = NewPermHandle(sizeof(TPrint));
  1934.             this->Reset();
  1935.         }
  1936.  
  1937.         if (wantValidate)
  1938.             this->ValidatePrintRecord(didChange);
  1939.     }
  1940.  
  1941.     //--------------------------------------------------------------------------------------------------
  1942. #pragma segment PrintNonRes
  1943.  
  1944.     pascal void TStdPrintHandler::SetMargins(void)
  1945.     {
  1946.         VRect someMargins;
  1947.  
  1948.         someMargins = fPageAreas.theMargins;
  1949.         this->InstallMargins(someMargins, fMinimalMargins);
  1950.     }
  1951.  
  1952.     //--------------------------------------------------------------------------------------------------
  1953. #pragma segment PrintImage
  1954.  
  1955.     pascal void TStdPrintHandler::SetPage(long aPageNumber)
  1956.     {
  1957.         VRect viewedRect;
  1958.         VPoint strip;
  1959.  
  1960.         fFocusedPage = aPageNumber;
  1961.         strip = this->PageToStrip(aPageNumber);
  1962.         for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1963.         {
  1964.             this->GetBreakCoord(gOrthogonal[vhs], strip[vhs], viewedRect[topLeft][vhs]);
  1965.             this->GetBreakCoord(gOrthogonal[vhs], strip[vhs] + 1, viewedRect[botRight][vhs]);
  1966.         }
  1967.  
  1968.         this->SetPageInterior(aPageNumber);
  1969.         fView->DoSetPageOffset(viewedRect[topLeft]);
  1970.         fViewedRect = viewedRect;
  1971.  
  1972. #if qDebug
  1973.         if (gDebugPrinting)
  1974.             cout << form("pg #: %1d;", aPageNumber) << " coord == " << viewedRect[topLeft] << " Page Interior: " << fPageAreas.theInterior << "\n";
  1975. #endif
  1976.  
  1977.     }
  1978.  
  1979.     //--------------------------------------------------------------------------------------------------
  1980. #pragma segment PrintNonRes
  1981.  
  1982.     pascal void TStdPrintHandler::SetPageInterior(long pageNumber)// override 
  1983.     {
  1984.         VPoint pegPoint;
  1985.  
  1986.         for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  1987.         {
  1988.             fPageAreas.theInterior[topLeft][vhs] = fPageAreas.thePaper[topLeft][vhs] + fPageAreas.theMargins[topLeft][vhs];
  1989.             fPageAreas.theInterior[botRight][vhs] = fPageAreas.theInterior[topLeft][vhs] + fViewPerPage[vhs];
  1990.         }
  1991.  
  1992.         this->LocatePageInterior(pageNumber, pegPoint);
  1993.         fPageAreas.theInterior[topLeft] = pegPoint;
  1994.         for (vhs = vSel; vhs <= hSel; ++vhs)
  1995.             fPageAreas.theInterior[botRight][vhs] = fPageAreas.theInterior[topLeft][vhs] + fViewPerPage[vhs];
  1996.     }
  1997.  
  1998.     //--------------------------------------------------------------------------------------------------
  1999. #pragma segment PrintImage
  2000.  
  2001.     pascal void TStdPrintHandler::SetPageOffset(const VPoint& coord)// override 
  2002.     {
  2003.         for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  2004.             gPageOffset[vhs] = coord[vhs] - fPageAreas.theInterior[topLeft][vhs];
  2005.     }
  2006.  
  2007.     //--------------------------------------------------------------------------------------------------
  2008. #pragma segment PrintFinder
  2009.  
  2010.     pascal Boolean TStdPrintHandler::SetupForFinder(void)// override 
  2011.     {
  2012.         Boolean proceed;
  2013.         Boolean didChange;
  2014.  
  2015.         proceed = TRUE;
  2016.         this->CheckPrinter();                            // Uncertain if necessary??? 
  2017.  
  2018.         if (fFinderSetup)
  2019.             this->PosePageSetupDialog(proceed, FALSE);
  2020.  
  2021.         if (proceed)
  2022.         {
  2023.             this->ShowDocBeingPrinted(TRUE);
  2024.             if (fFinderJobDialog ||!gFinderHPrint)
  2025.             {
  2026.                 proceed = this->PoseJobDialog();
  2027.                 // Merge into gPrintHandler, in case next document needs it 
  2028.                 if (!gFinderHPrint)
  2029.                     gFinderHPrint = NewPermHandle(sizeof(TPrint));
  2030.  
  2031.                 BlockMove((*fHPrint), (*gFinderHPrint), sizeof(TPrint));
  2032.             }
  2033.             else
  2034.             {
  2035.                 PrJobMerge((THPrint)gFinderHPrint, (THPrint)fHPrint);
  2036.                 this->ValidatePrintRecord(didChange);
  2037.             }
  2038.             this->ShowDocBeingPrinted(FALSE);
  2039.         }
  2040.         return proceed;
  2041.     }
  2042.  
  2043.     //--------------------------------------------------------------------------------------------------
  2044. #pragma segment PrintRes
  2045.  
  2046.     pascal Boolean TStdPrintHandler::SetupPrintOne(void)
  2047.     {
  2048.         Boolean didChange;
  2049.  
  2050.         // Call PrValidate to 1) make sure the record is OK, and
  2051.         // 2) Get the LaserWriter driver to get the name of the front window.
  2052.         this->ValidatePrintRecord(didChange);
  2053.  
  2054.         PrSetError(noErr);
  2055.         ((TPPrint) * fHPrint)->prJob.iFstPage = 0;
  2056.         ((TPPrint) * fHPrint)->prJob.iLstPage = 9999;// This is what the Print Mgr. uses 
  2057.         return TRUE;                            // Should always be able to continue from here
  2058.     }
  2059.  
  2060.     //--------------------------------------------------------------------------------------------------
  2061. #pragma segment PrintFinder
  2062.  
  2063.     pascal void TStdPrintHandler::ShowDocBeingPrinted(Boolean entering)
  2064.     {
  2065.         Str255 aTitle;
  2066.  
  2067.         if (entering)
  2068.         {
  2069.             fPrintDialog = GetNewDialog(phWhichDoc, (Ptr)NULL, (WindowPtr) - 1);
  2070.             if (fPrintDialog)
  2071.             {
  2072.                 this->GetDocName(aTitle);
  2073.                 SetWTitle(fPrintDialog, aTitle);
  2074.                 DrawDialog(fPrintDialog);
  2075.             }
  2076. #if qDebug
  2077.             else
  2078.                 ProgramBreak(ConcatNumber("Unable to load dialog ", phWhichDoc));
  2079. #endif
  2080.  
  2081.         }
  2082.         else
  2083.             this->BanishPrintDialog();
  2084.     }
  2085.  
  2086.     //--------------------------------------------------------------------------------------------------
  2087. #pragma segment PrintRes
  2088.  
  2089.     pascal Boolean TStdPrintHandler::ShowsOnScreen(void)
  2090.     {
  2091.         if (fView)
  2092.             return fView->IsVisible();
  2093.         else
  2094.             return FALSE;
  2095.     }
  2096.  
  2097.     //--------------------------------------------------------------------------------------------------
  2098. #pragma segment PrintRes
  2099.  
  2100.     pascal long TStdPrintHandler::StripToPage(long hStrip,
  2101.                                               long vStrip)
  2102.     {
  2103.         Point strip((short)vStrip, (short)hStrip);
  2104.         VHSelect ortho;
  2105.  
  2106.         ortho = gOrthogonal[fPageDirection];
  2107.         return strip[fPageDirection] * fPageStrips[ortho] + strip[ortho] + fStartPage;
  2108.     }
  2109.  
  2110.     //--------------------------------------------------------------------------------------------------
  2111. #pragma segment PrintRes
  2112.  
  2113.     pascal void TStdPrintHandler::ValidatePrintRecord(Boolean& didChange)
  2114.     {
  2115.         FailInfo fi;
  2116.         CPrintDialogs aPrValidateDialog(didChange, fHPrint);
  2117.  
  2118.         if (!fi.CatchFailure())
  2119.         {
  2120.             this->DoInMacPrint((WhatToDoType) & CPrintDialogs::CallPrValidate, &aPrValidateDialog);
  2121.             fi.Success();
  2122.         }
  2123.         else
  2124.             this->Reset();
  2125.     }
  2126.  
  2127.     //--------------------------------------------------------------------------------------------------
  2128. #pragma segment PrintDoCommand
  2129.  
  2130.     pascal void TPrintStyleChangeCommand::Initialize(void)// override 
  2131.     {
  2132.         inherited::Initialize();
  2133.         fNewHPrint = NULL;
  2134.         fOldHPrint = NULL;
  2135.         fStdPrintHandler = NULL;
  2136.     }
  2137.  
  2138.     //--------------------------------------------------------------------------------------------------
  2139. #pragma segment PrintDoCommand
  2140.  
  2141.     pascal void TPrintStyleChangeCommand::IPrintStyleChangeCommand(TStdPrintHandler* itsPrintHandler)
  2142.     {
  2143.         TDocument * changedDocument;
  2144.         FailInfo fi;
  2145.  
  2146.         changedDocument = itsPrintHandler->fDocument;
  2147.         this->ICommand(cChangePrinterStyle, changedDocument, itsPrintHandler->fView);
  2148.         fStdPrintHandler = itsPrintHandler;
  2149.         fCausesChange = (changedDocument && (changedDocument->fSavePrintInfo));
  2150.         if (!fi.CatchFailure())
  2151.         {
  2152.             fOldHPrint = NewPermHandle(sizeof(TPrint));
  2153.             // Make a copy of the old version of the PrintInfo record 
  2154.             BlockMove(*(itsPrintHandler->fHPrint), *fOldHPrint, sizeof(TPrint));
  2155.             fNewHPrint = NewPermHandle(sizeof(TPrint));
  2156.             fi.Success();
  2157.         }
  2158.         else
  2159.         {
  2160.             this->Free();
  2161.             fi.ReSignal();
  2162.         }
  2163.     }
  2164.  
  2165.     //--------------------------------------------------------------------------------------------------
  2166. #pragma segment PrintDoCommand
  2167.  
  2168.     pascal void TPrintStyleChangeCommand::Free(void)// override 
  2169.     {
  2170.         fOldHPrint = DisposeIfHandle(fOldHPrint);
  2171.         fNewHPrint = DisposeIfHandle(fNewHPrint);
  2172.         inherited::Free();
  2173.     }
  2174.  
  2175.     //--------------------------------------------------------------------------------------------------
  2176. #pragma segment PrintDoCommand
  2177.  
  2178.     pascal void TPrintStyleChangeCommand::DoIt(void)// override 
  2179.     {
  2180.         fStdPrintHandler->CheckPrinter();        // Will find it changed, and hence dispatch
  2181.         // to view's DoPrinterChanged
  2182.     }
  2183.  
  2184.     //--------------------------------------------------------------------------------------------------
  2185. #pragma segment PrintFields
  2186.  
  2187.     pascal void TPrintStyleChangeCommand::Fields(TObject* obj)
  2188.     {
  2189.         obj->DoToField("TPrintStyleChangeCommand", NULL, bClass);
  2190.         obj->DoToField("fStdPrintHandler", &fStdPrintHandler, bObject);
  2191.         obj->DoToField("fOldHPrint", &fOldHPrint, bHandle);
  2192.         obj->DoToField("fNewHPrint", &fNewHPrint, bHandle);
  2193.  
  2194.         inherited::Fields(obj);
  2195.     }
  2196.  
  2197.     //--------------------------------------------------------------------------------------------------
  2198. #pragma segment PrintDoCommand
  2199.  
  2200.     pascal void TPrintStyleChangeCommand::UndoIt(void)// override 
  2201.  
  2202.     {
  2203.         BlockMove(*fOldHPrint, *(fStdPrintHandler->fHPrint), sizeof(TPrint));
  2204.         fStdPrintHandler->CheckPrinter();        // Will find it changed, and hence dispatch
  2205.         // to view's DoPrinterChanged
  2206.     }
  2207.  
  2208.     //--------------------------------------------------------------------------------------------------
  2209. #pragma segment PrintDoCommand
  2210.  
  2211.     pascal void TPrintStyleChangeCommand::RedoIt(void)// override 
  2212.     {
  2213.         BlockMove(*fNewHPrint, *(fStdPrintHandler->fHPrint), sizeof(TPrint));
  2214.         fStdPrintHandler->CheckPrinter();        // Will find it changed, and hence dispatch
  2215.         // to view's DoPrinterChanged
  2216.     }
  2217.  
  2218.  
  2219.